﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data.SqlClient;
using System.Text;
namespace TestWS
{
    /// <summary>
    /// Summary description for serviciointegrador
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class serviciointegrador : System.Web.Services.WebService
    {
        [WebMethod]
        public List<datosmini> cargardatosmini()
        {
            SqlConnection oCon;
            oCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            List<datosmini> dmini = new List<datosmini>();

            SqlCommand oCom;
            string SelectSQL = "SELECT * FROM minimizar";
            oCom = new SqlCommand(SelectSQL, oCon);

            SqlDataReader oLector;
            oCon.Open();
            oLector = oCom.ExecuteReader();
            while (oLector.Read())
            {
                int varobj = int.Parse(oLector["varobj"].ToString());
                float valorobj = float.Parse(oLector["valorobj"].ToString());
                float? cotainferior = float.Parse(oLector["cotainferior"].ToString());
                float? cotasuperior = null;
                if (oLector["cotasuperior"] != System.DBNull.Value)
                    cotasuperior = float.Parse(oLector["cotasuperior"].ToString());
                dmini.Add(new datosmini(varobj, valorobj, cotainferior, cotasuperior));
            }
            oLector.Close();
            oCon.Close();
            return dmini;
        }
        [WebMethod]
        public List<datosrestric> cargardatosrestric()
        {
            SqlConnection oCon;
            oCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            List<datosrestric> dmini = new List<datosrestric>();

            SqlCommand oCom;
            string SelectSQL = "SELECT * FROM restriccion";
            oCom = new SqlCommand(SelectSQL, oCon);

            SqlDataReader oLector;
            oCon.Open();
            oLector = oCom.ExecuteReader();
            while (oLector.Read())
            {
                int idrestric = int.Parse(oLector["idrestriccion"].ToString());
                int idvarobj1 = int.Parse(oLector["idvarobj1"].ToString());
                float valorobj1 = float.Parse(oLector["valorobj1"].ToString());
                int idvarobj2 = int.Parse(oLector["idvarobj2"].ToString());
                float valorobj2 = float.Parse(oLector["valorobj2"].ToString());
                char tiporestric = char.Parse(oLector["tiporestriccion"].ToString());
                float valorrestric = float.Parse(oLector["valorrestriccion"].ToString());
                dmini.Add(new datosrestric(idrestric, idvarobj1, valorobj1, idvarobj2, valorobj2, tiporestric, valorrestric));
            }
            oLector.Close();
            oCon.Close();
            return dmini;
        }
        [WebMethod]
        public string hw() { return ""; }
        public void APIErrorCheck(IntPtr pEnv, int nErr)
        {
            if (nErr > 0)
            {
                StringBuilder cMessage = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);
                lindo.LSgetErrorMessage(pEnv, nErr, cMessage);
                //this.lblMsg.Text = cMessage.ToString();
            }
        }
        [WebMethod]
        public string callindo(List<datosmini> dm, List<datosrestric> dr)
        {

            int nErrorCode = lindo.LSERR_NO_ERROR;

            /* Número de restricciones */
            int nCons = 2;

            /* Número de variables de decisión */
            int nVars = 2;

            /* Se declara una variable que nos va a permitir comunicarnos con LINDO */
            IntPtr pEnv = (IntPtr)0;

            /* Se declara una variable que nos va a permitir tratar con el modelo */
            IntPtr pModel = (IntPtr)0;

            int nSolStatus = lindo.LS_STATUS_UNKNOWN;

            StringBuilder LicenseKey = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);

            /* >>> PASO 1 <<< Lograr la comunicación con LINDO */
            nErrorCode = lindo.LSloadLicenseString(@"C:\Lindoapi\license\lndapi90.lic", LicenseKey);
            APIErrorCheck(pEnv, nErrorCode);

            pEnv = lindo.LScreateEnv(ref nErrorCode, LicenseKey.ToString());
            if (nErrorCode == lindo.LSERR_NO_VALID_LICENSE)
            {
                return "¡LICENCIA NO VÁLIDA!\n";
            }
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 2 <<< Crear el modelo */
            pModel = lindo.LScreateModel(pEnv, ref nErrorCode);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 3 <<< Especificar el modelo */

            /* El tipo de optimización */
            int nDir = lindo.LS_MAX;

            /* El término constante de la función objetivo */
            double dObjConst = 0;

            /* Los coeficientes de la función objetivo */
            double[] adC = new double[nVars];
            foreach (datosmini dm1 in dm)
            {
                if (dm1.varobj == 1)
                {
                    adC[0] = double.Parse(dm1.valorobj.ToString());
                }
                else
                {
                    adC[1] = double.Parse(dm1.valorobj.ToString());
                }
            }
            /* El lado derecho de las restricciones */
            double[] adB = new double[nCons];
            foreach (datosrestric dr1 in dr)
            {
                if (dr1.idrestric == 1)
                {

                    adB[0] = double.Parse(dr1.valorrestric.ToString());
                }
                else
                {

                    adB[1] = double.Parse(dr1.valorrestric.ToString());
                }
            }
            /* Los tipos de restricciones */
            string acConTypes = "LL";


            /* El número de elementos que NO son cero en la matriz de restricciones */
            int nNZ = 11;

            /* La posición del primer elemento NO cero de cada columna */
            int[] anBegCol = new int[] { 0, 1, nNZ };

            /* La longitud de cada columna en cuanto a los elementos que NO son cero */
            int[] pnLenCol = new int[] { 2, 2 };

            /* Los coeficientes que NO son cero por columna */
            double[] adA = new double[] { 1, 1, 1, 1 };

            /* La posición por fila de los elementos que NO son cero */
            int[] anRowX = new int[] { 0, 1, 0, 1 };

            /* Cotas inferiores y superiores de cada variable */
            double[] pdLower = new double[] { 0, 0 };
            double[] pdUpper = new double[] { lindo.LS_INFINITY, lindo.LS_INFINITY };

            /* Nombres de variables y restricciones */
            string[] varnames = new string[] { "X1", "X2", "X3", "X4", "Y1", "Y2", "Y3", "Y4" };
            string[] connames = new string[] { "R1", "R2", "R3", "R4" };

            /* Cargamos el modelo */
            nErrorCode = lindo.LSloadLPData(pModel, nCons, nVars, nDir,
                dObjConst, adC, adB, acConTypes, nNZ, anBegCol,
                pnLenCol, adA, anRowX, pdLower, pdUpper);
            APIErrorCheck(pEnv, nErrorCode);

            nErrorCode = lindo.LSloadNameData(pModel, "Plan de Producción", null, null, null,
            null, connames, varnames, null);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 4 <<< Correr el modelo matemático */
            nErrorCode = lindo.LSoptimize(pModel, lindo.LS_METHOD_PSIMPLEX, ref nSolStatus);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 5 <<< Tomar la salida de la optimización */

            /* Se toma el valor de la función objetivo */
            double dObj = 0;
            nErrorCode = lindo.LSgetInfo(pModel, lindo.LS_DINFO_POBJ, ref dObj);
            APIErrorCheck(pEnv, nErrorCode);
            // Se atrapa el valor de la función objetivo

            /* Se toman los valores de las variables */
            double[] adX = new double[nVars];
            nErrorCode = lindo.LSgetPrimalSolution(pModel, adX);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 6 <<< Borramos el modelo de LINDO y cortamos la comunicación con el SOLVER */
            nErrorCode = lindo.LSdeleteModel(ref pModel);
            nErrorCode = lindo.LSdeleteEnv(ref pEnv);
            return string.Format("F.O.={0}  X1={1}  X1={2}", dObj, adX[0].ToString(), adX[1].ToString());
        }
    }
}
